package com.ruoyi.business.controller;

import java.io.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.business.domain.Beds;
import com.ruoyi.business.domain.Dormitory;
import com.ruoyi.business.domain.Employee;
import com.ruoyi.business.domain.bo.BedsBo;
import com.ruoyi.business.domain.model.*;
import com.ruoyi.business.domain.vo.BedsVo;
import com.ruoyi.business.domain.vo.EmployeeVo;
import com.ruoyi.business.service.*;
import com.ruoyi.common.annotation.Translation;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtilPlus;
import com.ruoyi.system.domain.SysNotice;
import com.ruoyi.system.service.ISysNoticeService;
import lombok.RequiredArgsConstructor;

import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*;

import cn.dev33.satoken.annotation.SaCheckPermission;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.http.MediaType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.core.validate.QueryGroup;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.business.domain.vo.DormitoryVo;
import com.ruoyi.business.domain.bo.DormitoryBo;
import com.ruoyi.common.core.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;

/**
 * 宿舍
 *
 * @author ruoyi
 * @date 2023-06-25
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/business/dormitory")
public class DormitoryController extends BaseController {

    private final IDormitoryService iDormitoryService;
    private final IBedsService iBedsService;
    private final IDormitoryPlusService dormitoryPlusService;
    private final IBedsPlusService bedsPlusService;
    private final IEmployeePlusService employeePlusService;
    private final ISysNoticeService sysNoticeService;

    /**
     * 查询宿舍列表
     */
    @SaCheckPermission("business:dormitory:list")
    @GetMapping("/list")
    public TableDataInfo<DormitoryVo> list(DormitoryBo bo, PageQuery pageQuery) {
        if (bo.getEmployeename()!=null||bo.getDepartment()!=null){
            LambdaQueryWrapper<Employee> queryWrapper=new LambdaQueryWrapper<>();
            if (bo.getEmployeename()!=null){
                queryWrapper.like(Employee::getFullName,bo.getEmployeename());
            }
            if (bo.getDepartment()!=null){
                queryWrapper.like(Employee::getDepartment,bo.getDepartment());
            }
            List<Employee> employeeList=employeePlusService.list(queryWrapper);
            if (employeeList.isEmpty()){
                return null;
            }
            List<Long> employeeIDList = employeeList.stream().map(Employee::getId).collect(Collectors.toList());

            LambdaQueryWrapper<Beds> queryWrapper_beds=new LambdaQueryWrapper<>();
            queryWrapper_beds.in(Beds::getEmployeeId,employeeIDList);
            List<Long> dormitoryIDList=bedsPlusService.list(queryWrapper_beds).stream().map(Beds::getDormitoryId).collect(Collectors.toList());
            if (dormitoryIDList.isEmpty()){
                return null;
            }
            TableDataInfo<DormitoryVo> result=iDormitoryService.getDormitoryIListByIds(dormitoryIDList);
            List<DormitoryVo> rows = result.getRows();
            for (DormitoryVo vo : rows) {
                List<BedsVo> children = bedsPlusService.getbedListBydormitoryid(vo.getId());
                vo.setChildren(children);
            }
            result.setRows(rows);
            return result;
        }else {
            TableDataInfo<DormitoryVo> result = iDormitoryService.queryPageList(bo, pageQuery);
            List<DormitoryVo> rows = result.getRows();
            for (DormitoryVo vo : rows) {
                List<BedsVo> children = bedsPlusService.getbedListBydormitoryid(vo.getId());
                vo.setChildren(children);
            }
            result.setRows(rows);
            return result;
        }

    }


    /**
     * 导出宿舍列表
     */
    @Log(title = "宿舍", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(DormitoryBo bo, HttpServletResponse response) {
        List<AccommodationInfo> list = iDormitoryService.getAccommodationInfoList(bo);
        ExcelUtilPlus<AccommodationInfo> util = new ExcelUtilPlus<AccommodationInfo>(AccommodationInfo.class);
        util.exportExcel(response, list, "宿舍入住信息");
    }

    /**
     * 获取宿舍详细信息
     *
     * @param id 主键
     */
    @GetMapping("/{id}")
    public R<DormitoryVo> getInfo(@NotNull(message = "主键不能为空")
                                  @PathVariable Long id) {
        return R.ok(iDormitoryService.queryById(id));
    }

    /**
     * 新增宿舍
     */
    @Log(title = "宿舍", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody DormitoryBo bo) {
        Dormitory saveModel = iDormitoryService.insertByBo2(bo);
        if (saveModel != null) {
            List<Beds> bedsList = new ArrayList<>();
            for (Integer i = 1; i <= saveModel.getCapacity(); i++) {
                Beds bedsModel = new Beds();
                bedsModel.setDormitoryId(saveModel.getId());
                bedsModel.setBedcode(i.toString());
                bedsModel.setStatus("空位");
                bedsList.add(bedsModel);

            }
            iBedsService.insertByBoBatch(bedsList);
        }
        return toAjax(true);
    }

    /**
     * 修改宿舍
     */
    @Log(title = "宿舍", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody DormitoryBo bo) {
        return toAjax(iDormitoryService.updateByBo(bo));
    }

    /**
     * 删除宿舍
     *
     * @param ids 主键串
     */
    @Log(title = "宿舍", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] ids) {
        return toAjax(iDormitoryService.deleteWithValidByIds(Arrays.asList(ids), true));
    }

    /**
     * 获取床位Tree
     */
    @GetMapping("/getbedtree")
    public List<buildTree> getbedtree(Dormitory bo) {
        LambdaQueryWrapper<Dormitory> query = new LambdaQueryWrapper<>();
        query.eq(Dormitory::getOutsource,bo.getOutsource());
        query.ne(Dormitory::getNature,"招待所");
        query.orderByAsc(Dormitory::getBuildingName);
        query.orderByAsc(Dormitory::getFloor);
        query.orderByAsc(Dormitory::getDormitoryId);
        List<Dormitory> dormitoryList = dormitoryPlusService.list(query);
        List<Beds> BedsList = bedsPlusService.list();
        //楼栋
        List<buildTree> buildTrees = dormitoryList.stream().map(dormitory -> new buildTree(1L, dormitory.getBuildingName(), null)).distinct().collect(Collectors.toList());
        for (buildTree b : buildTrees) {
            //楼层
            List<floorTree> floorTrees = dormitoryList.stream().filter(x -> x.getBuildingName().equals(b.getLabel())).map(p -> {
                return new floorTree(2L, p.getFloor().toString(), null);
            }).distinct().collect(Collectors.toList());
            b.setChildren(floorTrees);

            for (floorTree f : floorTrees) {
                //楼层的房间
                List<dormitoryTree> dormitoryTrees = dormitoryList.stream().filter(x -> x.getBuildingName().equals(b.getLabel()) && x.getFloor().toString().equals(f.getLabel())).map(p -> {
                    return new dormitoryTree(p.getId(), p.getDormitoryId() + "/" + p.getGender() + "/" + p.getNature(), null);
                }).collect(Collectors.toList());
                f.setChildren(dormitoryTrees);
                for (dormitoryTree d : dormitoryTrees) {
                    //每个房间的床位
                    List<bedTree> bedTrees = BedsList.stream().filter(x -> x.getDormitoryId().equals(d.getValue())).map(p -> {
                        return new bedTree(p.getId(), p.getBedcode() + "/" + p.getStatus());
                    }).collect(Collectors.toList());
                    d.setChildren(bedTrees);
                }
            }
        }
        return buildTrees;
    }



    /**
     * 分派宿舍
     */
    @Transactional(rollbackFor = Exception.class)
    @Log(title = "分派宿舍", businessType = BusinessType.UPDATE)
    @PostMapping("/assign")
    public R<Void> assign(@RequestBody DormitoryAndEmployee dormitoryAndEmployee) {
        if (dormitoryAndEmployee.getBedIds() == null) {
            //没有选择宿舍，就是退出宿舍
            List<String> employeeIds = dormitoryAndEmployee.getEmployeeIds();
            for (String employeeId : employeeIds) {
                LambdaUpdateWrapper<Employee> update_Employee_sql = new LambdaUpdateWrapper<Employee>().set(Employee::getRoomNumber, null).set(Employee::getAllocated,null).eq(Employee::getId, employeeId);
                employeePlusService.update(update_Employee_sql);
                //先清空之前的床位
                LambdaUpdateWrapper<Beds> update_beds_sql2 = new LambdaUpdateWrapper<Beds>().set(Beds::getEmployeeId, null).set(Beds::getStatus, "空位").eq(Beds::getEmployeeId, employeeId);
                bedsPlusService.update(update_beds_sql2);
                Employee employeeModel=employeePlusService.getById(employeeId);
                SysNotice notice=new SysNotice();
                String noticeTitle = String.format("员工%s已被退出宿舍", employeeModel.getFullName());
                notice.setNoticeTitle(noticeTitle);
                notice.setNoticeType("1");
                notice.setStatus("0");
                sysNoticeService.insertNotice(notice);
            }
            return R.ok();
        }
        Map<String, String> mappedIds = mapIds(dormitoryAndEmployee.getEmployeeIds(), dormitoryAndEmployee.getBedIds());
        for (Map.Entry<String, String> entry : mappedIds.entrySet()) {
            String employeeId = entry.getKey();//员工id
            String mappedId = entry.getValue();//床位id
            LambdaUpdateWrapper<Employee> update_Employee_sql = new LambdaUpdateWrapper<Employee>().set(Employee::getRoomNumber, mappedId).set(Employee::getAllocated, "已办").eq(Employee::getId, employeeId).eq(Employee::getAccommodation, "是");
            if (employeePlusService.update(update_Employee_sql)) {
                //先清空之前的床位，然后再赋予床位
                LambdaUpdateWrapper<Beds> update_beds_sql2 = new LambdaUpdateWrapper<Beds>().set(Beds::getEmployeeId, null).set(Beds::getStatus, "空位").eq(Beds::getEmployeeId, employeeId);
                bedsPlusService.update(update_beds_sql2);
                LambdaUpdateWrapper<Beds> update_beds_sql = new LambdaUpdateWrapper<Beds>().set(Beds::getEmployeeId, employeeId).set(Beds::getStatus, "已占位").set(Beds::getUpdateTime, new DateTime()).eq(Beds::getId, mappedId);
                bedsPlusService.update(update_beds_sql);
            }

            Employee employeeModel=employeePlusService.getById(employeeId);
            SysNotice notice=new SysNotice();
            String noticeTitle = String.format("%s 已被分配宿舍", employeeModel.getFullName());
            notice.setNoticeTitle(noticeTitle);
            notice.setNoticeType("办住");
            notice.setStatus("0");
            notice.setJobNumber(employeeModel.getJobNumber());
            notice.setFullName(employeeModel.getFullName());
            notice.setIdNumber(employeeModel.getIdNumber());
            notice.setDepartment(employeeModel.getDepartment());
            notice.setRoomNumber(bedsPlusService.getbedDetailByid(mappedId));
            sysNoticeService.insertNotice(notice);
        }
        return R.ok();
    }

    private static Map<String, String> mapIds(List<String> employeeIds, List<List<Object>> bedIds) {
        Map<String, String> mappedIds = new HashMap<>();
        for (int i = 0; i < employeeIds.size(); i++) {
            String employeeId = employeeIds.get(i);
            if (i < bedIds.size()) {
                List<Object> bedId = bedIds.get(i);
                String mappedId;

                if (bedId.size() >= 4) {
                    mappedId = bedId.get(3).toString();
                } else if (bedId.size() >= 3) {
                    mappedId = bedId.get(2).toString();
                } else {
                    mappedId = "";  // 如果没有第三个和第四个值，则对应为空字符串
                }

                mappedIds.put(employeeId, mappedId);
            }
        }

        return mappedIds;
    }

    /**
     * 导入宿舍
     */
    @Log(title = "导入宿舍", businessType = BusinessType.IMPORT)
    @PostMapping(value = "/importData2", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public R<Void> importData2(@RequestPart("file") MultipartFile file, boolean updateSupport) throws Exception {
       // List<Dormitory> listdories=new ArrayList<Dormitory>();
        Workbook workbook = new XSSFWorkbook(file.getInputStream());
        Sheet sheet = workbook.getSheetAt(0); // 假设数据在第一个工作表中
        int rowIndex = 2; // 从第三行开始遍历数据
        // 遍历每行数据
        for (int i = rowIndex; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            if (row != null) {
                // 读取房间号和表底数据
                Cell cell1 = row.getCell(1); // 楼号
                Cell cell2 = row.getCell(2); // 房间号
                Cell cell3 = row.getCell(3); // 床位数
                Cell cell4 = row.getCell(4); // 性质
                Cell cell5 = row.getCell(5); // 是否外包
                // 检查单元格是否为空
                DormitoryBo dormitory = new DormitoryBo();
                if (cell1 != null) {
                    String builname = cell1.getStringCellValue();
                    dormitory.setBuildingName(builname);
                }
                if (cell2 != null) {
                    String[] cell2s = cell2.getStringCellValue().split("#");
                    dormitory.setFloor(Integer.parseInt(cell2s[1].substring(0, 1)));
                    dormitory.setDormitoryId(cell2s[1]);
                }
                if (cell3 != null) {
                    //设置单元格类型
                    cell3.setCellType(CellType.STRING);
                    String capacity = cell3.getStringCellValue();
                    dormitory.setCapacity(convertToInt(capacity));
                }
                if (cell4 != null) {
                    String nature = cell4.getStringCellValue();
                    if (nature.contains("男")) {
                        dormitory.setGender("男");
                        if (nature.contains("大学生")){
                            dormitory.setNature("大学生");
                        }else {
                            dormitory.setNature("宿舍");
                        }

                    } else if (nature.contains("女")) {
                        dormitory.setGender("女");
                        if (nature.contains("大学生")){
                            dormitory.setNature("大学生");
                        }else {
                            dormitory.setNature("宿舍");
                        }
                    } else {
                        dormitory.setGender("男");
                        dormitory.setNature(nature);
                    }
                }
                if (cell5 != null) {
                    String outsource = cell5.getStringCellValue();
                    if (outsource.equals("是") || outsource.equals("轧钢外包")) {
                        dormitory.setOutsource("是");

                    } else {
                        dormitory.setOutsource("否");
                    }
                }
                try {
                    this.add(dormitory);
                }catch (Exception e) {

                    //Cell cell0 = row.getCell(0); // 楼号
                    System.out.println( i+"行数据出错");
                }

            }

        }

       // dormitoryPlusService.saveBatch(listdories);
        workbook.close(); // 关闭Workbook对象
        return R.ok();
    }

    public int convertToInt(String capacity) {
        try {
            return Integer.parseInt(capacity);
        } catch (NumberFormatException e) {
            return 0;
        }
    }

    /**
     * 导入住宿的人员
     */
    @Log(title = "导入住宿的人员", businessType = BusinessType.IMPORT)
    @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public R<Void> importData(@RequestPart("file") MultipartFile file, boolean updateSupport) throws Exception {
        // 创建一个临时文件来保存修改后的内容
        StringBuilder sb = new StringBuilder();
        Workbook workbook = new XSSFWorkbook(file.getInputStream());
        Sheet sheet = workbook.getSheetAt(0); // 假设数据在第一个工作表中
        int rowIndex = 1; // 从第2行开始遍历数据
        // 遍历每行数据
        for (int i = rowIndex; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            if (row != null) {
                // 读取房间号和表底数据
                Cell cell1 = row.getCell(1); // 房间号
                //Cell cell2 = row.getCell(3); // 姓名
                Cell cell3 = row.getCell(2); // 工号

                String bildingname=null;
                String dormiorid=null;
                String gonghao=null;
                if (cell1 != null) {
                    String c1 = cell1.getStringCellValue();
                     bildingname=c1.split("#")[0]+"#楼";
                     dormiorid=c1.split("#")[1];
                }
                if (cell3 != null) {
                    cell3.setCellType(CellType.STRING);
                     gonghao = cell3.getStringCellValue();
                }

                try {
                    List<Beds> bedsList=  bedsPlusService.getbedListBydormitory(dormiorid,bildingname);
                    if (bedsList.size()>0){
                        Beds bed=bedsList.get(0);
                        if (gonghao!=null){
                            LambdaQueryWrapper<Employee> queryWrapper=new LambdaQueryWrapper<>();
                            queryWrapper.eq(Employee::getJobNumber,gonghao);
                            Employee employee=employeePlusService.getOne(queryWrapper);
                            if (employee!=null){
                                bed.setEmployeeId(employee.getId());
                                bed.setStatus("已占位");
                                bed.setUpdateTime(new DateTime());
                                employee.setRoomNumber(bed.getId().toString());
                                bedsPlusService.updateById(bed);
                                employeePlusService.updateById(employee);
                            }else {
                                sb.append("第"+i+"序列,未找到对应员工;").append("\n");
                            }
                        }else {
                            sb.append("第"+i+"序列,工号不能为空;").append("\n");
                        }

                    }else {
                        sb.append("第"+i+"序列,未找到对应宿舍或已住满;").append("\n");
                    }
                }catch (Exception e) {
                    sb.append("第"+i+"序列,处理出错;").append("\n");
                }
            }
        }
        workbook.close();
        return R.ok(sb.toString());
    }

    /**
     * 获取宿舍Tree（App使用）
     */
    @GetMapping("/getDormitorytree")
    public List<buildAppTree> getDormitorytree() {
        List<Dormitory> dormitoryList = dormitoryPlusService.list();
        //楼栋
        List<buildAppTree> buildAppTrees = dormitoryList.stream().map(dormitory -> new buildAppTree("1", dormitory.getBuildingName(), null)).distinct().collect(Collectors.toList());
        for (buildAppTree b : buildAppTrees) {

            //楼层
            List<floorAppTree> floorAppTrees = dormitoryList.stream().filter(x -> x.getBuildingName().equals(b.getText())).map(p -> {
                return new floorAppTree("2", p.getFloor().toString(), null);
            }).distinct().collect(Collectors.toList());
            b.setValue(UUID.randomUUID().toString());
            b.setChildren(floorAppTrees);
            for (floorAppTree f : floorAppTrees) {
                //楼层的房间
                List<dormitoryAppTree> dormitoryAppTrees = dormitoryList.stream().filter(x -> x.getBuildingName().equals(b.getText()) && x.getFloor().toString().equals(f.getText())).map(p -> {
                    return new dormitoryAppTree(p.getId().toString(), p.getDormitoryId());
                }).collect(Collectors.toList());
                f.setValue(UUID.randomUUID().toString());
                f.setChildren(dormitoryAppTrees);

            }
        }
        return buildAppTrees;
    }
    /**
     * 获取宿舍到楼层Tree（App使用）
     */
    @GetMapping("/getDormitoryFloortree")
    public List<buildAppTree> getDormitoryFloortree() {
        List<Dormitory> dormitoryList = dormitoryPlusService.list();
        //楼栋
        List<buildAppTree> buildAppTrees = dormitoryList.stream().map(dormitory -> new buildAppTree("1", dormitory.getBuildingName(), null)).distinct().collect(Collectors.toList());
        for (buildAppTree b : buildAppTrees) {

            //楼层
            List<floorAppTree> floorAppTrees = dormitoryList.stream().filter(x -> x.getBuildingName().equals(b.getText())).map(p -> {
                return new floorAppTree("2", p.getFloor().toString(), null);
            }).distinct().collect(Collectors.toList());
            b.setValue(UUID.randomUUID().toString());
            b.setChildren(floorAppTrees);

        }
        return buildAppTrees;
    }
    /**
     * 获取楼栋名称（App使用）
     */
    @GetMapping("/getbuildingName")
    public List<String> getbuildingName() {
        List<String> bildnameList = dormitoryPlusService.bildnameList();
        return bildnameList;
    }
    /**
     * 根据楼栋名称和楼层获取所有房间（App使用）
     */
    @GetMapping("/getroomName")
    public List<dormitoryAppTree> getroomName(Dormitory bo) {
        List<dormitoryAppTree> bildnameList = dormitoryPlusService.getroomList(bo.getBuildingName(),bo.getFloor().toString());
        return bildnameList;
    }

}
